package require TclOO

oo::class create CharmmPar {
    variable top par
}

oo::define CharmmPar method load { topfile parfile } {
    set rfile [open $topfile r]
    set top [read $rfile]
    close $rfile
    set rfile [open $parfile r]
    set par [read $rfile]
    close $rfile
    my getRes
    my getPar
}
oo::define CharmmPar method getRes {} {
    my variable Residues
    my variable Patches
    my variable Atoms
    my variable Atomtype
    set Residues(names) {}
    set Atomtype {}
    #get idxes
    set idxes [regexp -inline -indices -all {RESI|PRES} $top]
    set i 0
    foreach idx $idxes {
	set idx [lindex $idx 0]
	set resname [string trim [string range $top $idx+5 $idx+8]]
	switch [string range $top $idx $idx+3] {
	    RESI { 
		lappend Residues(names) $resname
		set Residues($resname,start) $idx
		if {$i < [llength $idxes]} {
		    set Residues($resname,end) [expr [lindex [lindex $idxes $i+1] 0]-1]
		} else {
		    set Residues($resname,end) [string length $top]
		}
		set Residues($resname,info) [string range $top $Residues($resname,start) $Residues($resname,end)]
	    }
	    PRES { lappend Patches(names) $resname
		set Patches($resname,start) $idx
		if {$i < [llength $idxes]} {
		    set Patches($resname,end) [expr [lindex [lindex $idxes $i+1] 0]-1]
		} else {
		    set Patches($resname,end) [string length $top]
		}
		set Patches($resname,info) [string range $top $Patches($resname,start) $Patches($resname,end)]
	    }
	}
	incr i
	
    }
    #debug
   # puts $Patches(names)
    #puts [array names Residues *,*]
    
    #process each residue
    foreach residue $Residues(names) {
	#get atoms
	set atoms [regexp -all -inline -lineanchor {^ATOM\s+(\w+)\s+(\w+)\s+([^\n]*)$} $Residues($residue,info)]
	set Residues($residue,atoms) {}
	#puts $residue
	#puts $atoms
	foreach {matched atomname type charge } $atoms {
	    lappend Residues($residue,atoms) $atomname
	    set Atoms($atomname,type) $type
	    set charge [scan $charge "%f"]
	    set Atoms($residue,$atomname,charge) $charge
	    if {[lsearch $Atomtype $type] <0 } { lappend Atomtype $type}
	}
	#debug
	#puts "$residue has $Residues($residue,atoms)"
	#get IC
	#
    }
   foreach residue $Patches(names) {
	#get atoms
	set atoms [regexp -all -inline -lineanchor {^ATOM\s+(\w+)\s+(\w+)\s+([^\n]*)$} $Patches($residue,info)]
	set Patches($residue,atoms) {}
	#puts $residue
	#puts $atoms
	foreach {matched atomname type charge } $atoms {
	    lappend Patches($residue,atoms) $atomname
	    set Atoms($atomname,type) $type
	    set charge [scan $charge "%f"]
	    set Atoms($residue,$atomname,charge) $charge
	    if {[lsearch $Atomtype $type] <0 } { lappend Atomtype $type}
	}
	#debug
	#puts "$residue has $Residues($residue,atoms)"
	#get IC
	#
    }
}


oo::define CharmmPar method getPar {} {
    my variable Atoms
    my variable Residues
    my variable Bonds
    my variable Atomtype
    my variable Atompar
    set i 1
    set idxes [regexp -inline -indices -all -lineanchor {^BOND|^THETAS|^PHI|^IMPHI|^CMAP|^NONBONDED|^NBFIX|^HBOND} $par]
    foreach idx $idxes {
	set sectionname [string range $par [lindex $idx 0] [lindex $idx 1]]
	set idx [lindex $idx 0]
	if {$i< [llength $idxes] } { 
	    set end [expr [lindex [lindex $idxes $i] 0]-1]
	} else {
	    set end [string length $par]
	}
	set section($sectionname) [string range $par $idx $end]
	incr i
    }
    #debug
    #parray section
    #process section(NOBONDED)

    #get 
    foreach line [split $section(NONBONDED) \n] {
	if { [set neglect [string first ! $line]] >= 0 } {
	    set line [string range $line 0 [string first ! $line]-1]
	}
	set result [regexp -all -inline {([\w%*]+)\s+(\S+)\s+(\S+)\s+(\S+)\s*(.*)} $line]
	if {[llength $result] <4 } { continue}
#	puts $result
	set atomtype [lindex $result 1]
	set polarizibility [lindex $result 2]
	set eps [lindex $result 3]
	set Rmin [lindex $result 4]
	set alternative [lindex $result 5]
#	puts "$atomtype $eps $Rmin"
	set idxes [lsearch -all $Atomtype $atomtype]
	foreach idx $idxes {
	    set name [lindex $Atomtype $idx]
	    set Atompar($name,eps) $eps
	    set Atompar($name,Rmin) $Rmin
	}
    }
}

oo::define CharmmPar method toPQRDAT {} {
    my variable Atomtype
    my variable Residues
    my variable Patches
    my variable Atoms
    my variable Atompar
    foreach res [lsort $Residues(names)] {
	foreach atom $Residues($res,atoms) {
	   # puts " $res $atom $Atoms($atom,charge) $Atompar($Atoms($atom,type),Rmin)  $Atoms($atom,type)"
	    set str [format "%-s\t%-s\t%-3.2f\t%-7.6f\t%-s" $res $atom $Atoms($res,$atom,charge) $Atompar($Atoms($atom,type),Rmin)  $Atoms($atom,type)]
	    puts $str
	}
    }
    foreach res [lsort $Patches(names)] {
	foreach atom $Patches($res,atoms) {
	    #puts " $res $atom $Atoms($atom,charge) $Atompar($Atoms($atom,type),Rmin)  $Atoms($atom,type)"
	    set str [format "%-s\t%-s\t%-3.2f\t%-7.6f\t%-s" $res $atom $Atoms($res,$atom,charge) $Atompar($Atoms($atom,type),Rmin)  $Atoms($atom,type)]
	    puts $str
	}
    }
}

CharmmPar create c19
c19 load toph19_eef1.1.inp param19_eef1.1.inp
c19 toPQRDAT
